package com.css.config.netty;

import com.css.config.base.ServerNode;
import com.css.config.base.SpringContext;
import com.css.config.netty.codec.PacketDecoder;
import com.css.config.netty.codec.PacketEncoder;
import com.css.config.netty.enums.PacketType;
import com.css.config.properties.NettyServerConfigs;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.GenericFutureListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;

/**
 * @author zyj
 * @description
 * @date 2019/7/18 17:29
 **/
public class ChatServer implements ServerNode {

    private Logger logger = LoggerFactory.getLogger(ChatServer.class);

    // 避免使用默认线程数参数
    private EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    private EventLoopGroup workerGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());
    private int port;//服务器端口

    @Override
    public void init() {
        NettyServerConfigs serverConfigs = SpringContext.getServerConfigs();
        this.port = serverConfigs.getSocketPort();
    }

    @Override
    public void start() throws Exception {
        logger.info("server begin start....");
        try{
            // 协议初始化
            PacketType.initPackets();
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childHandler(new ChildChannelHandler());
            ChannelFuture f = b.bind(new InetSocketAddress(port)).sync();
            f.addListener(new GenericFutureListener<ChannelFuture>() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    logger.info("Netty init over,result:{}", future.isSuccess());
                }
            });
        } catch (Exception e){
            logger.error("server start error", e);
            throw e;
        }
        logger.info("server success start....");
    }

    @Override
    public void shutDown() throws Exception {

    }


    private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
        @Override
        protected void initChannel(SocketChannel arg0) throws Exception {
            ChannelPipeline pipeline = arg0.pipeline();
            pipeline.addLast(new PacketDecoder(1024 * 1024, 0, 4, 0, 4));
            pipeline.addLast(new LengthFieldPrepender(4));
            pipeline.addLast(new PacketEncoder());
            // 客户端300秒没收发包，便会触发UserEventTriggered事件到MessageTransportHandler
            pipeline.addLast("idleStateHandler", new IdleStateHandler(0, 0, 30000));
            pipeline.addLast(new IoHandler());
        }
    }
}
